home *** CD-ROM | disk | FTP | other *** search
- /*
-
- binder.cpp
- 10-25-91
- Loose Data Binder v 1.5
-
- Copyright 1991
- John W. Small
- All rights reserved
-
- PSW / Power SoftWare
- P.O. Box 10072
- McLean, Virginia 22102 8072 USA
-
- John Small
- Voice: (703) 759-3838
- CIS: 73757,2233
-
- */
-
-
- #include <string.h>
- #include "binder.hpp"
-
- void Binder::construct(unsigned flags, unsigned maxNodes,
- unsigned limit, unsigned delta)
- {
- curNode = first = nodes = 0;
- comparE = BDRcomparE0;
-
- /*
- The following relationships are maintained
- during operation of a binder:
-
- 1 <= delta <= lowLimit <= limit <= maxNodes
- <= BDR_MAXNODES
- lowThreshold = lowLimit - delta;
- */
-
- if (maxNodes > BDR_MAXNODES)
- maxNodes = BDR_MAXNODES;
- if (limit > maxNodes)
- limit = maxNodes;
- if (delta > limit)
- delta = limit;
- if (!delta) {
- delta = 1;
- if (limit < delta)
- limit = delta;
- if (maxNodes < limit)
- maxNodes = limit;
- }
- if ((linkS = new voiD[limit]) == voiDV0)
- this->limit = lowLimit = lowThreshold
- = this->delta = this->maxNodes
- = this->flags = 0;
- else {
- this->limit = limit;
- this->delta = delta;
- this->maxNodes = maxNodes;
- lowLimit = limit;
- lowThreshold = lowLimit - delta;
- this->flags = ((flags & BDR_OK_FREE)
- | BDR_SORTED);
- }
- }
-
- Binder::Binder(voiDV argv, int argc, unsigned flags)
- {
- construct(flags,BDR_MAXNODES,argc,BDR_DELTA);
- if (argv) if (argc > 0)
- while (argc--)
- push(argv[argc]);
- else
- for (argc = 0; insQ(argv[argc]); argc++);
- }
-
- voiDV Binder::vector()
- {
- voiDV V = voiDV0;
-
- if (nodes) if ((V = new voiD[nodes+1]) != voiDV0) {
- for (unsigned i = 0; i < nodes; i++)
- V[i] = atGet(i);
- V[i] = voiD0;
- }
- return V;
- }
-
- Binder::~Binder()
- {
- if (flags & BDR_OK_FREE)
- allFree();
- else
- allDel();
- if (linkS)
- delete linkS;
- }
-
- unsigned Binder::setLimit(unsigned newLimit)
- {
- voiDV newLinkS;
- unsigned i;
-
- if (newLimit < nodes)
- newLimit = nodes;
- else if (newLimit > maxNodes)
- newLimit = maxNodes;
- if (newLimit < delta)
- newLimit = delta;
- if (!linkS || !newLimit || newLimit == limit)
- return 0;
- if ((newLinkS = new voiD[newLimit]) == voiDV0)
- return 0;
- if ((i = limit - first) > nodes)
- i = nodes;
- memcpy(newLinkS,&linkS[first],sizeof(linkS[0])*i);
- /* copy wrap around */
- if (i < nodes)
- memcpy(&newLinkS[i],linkS,
- sizeof(linkS[0])*(nodes-i));
- if (newLimit > limit)
- if (newLimit - delta > limit)
- lowLimit = newLimit - delta;
- else
- lowLimit = limit;
- else
- if (newLimit - delta > delta)
- lowLimit = newLimit - delta;
- else
- lowLimit = delta;
- lowThreshold = lowLimit - delta;
- delete linkS;
- linkS = newLinkS;
- limit = newLimit;
- first = 0;
- return limit;
- }
-
- unsigned Binder::setDelta(unsigned newDelta)
- {
- return ((newDelta && newDelta <= lowLimit)?
- delta = newDelta : 0);
- }
-
- unsigned Binder::setMaxNodes(unsigned newMaxNodes)
- {
- return ((newMaxNodes >= limit)?
- (maxNodes = (newMaxNodes
- > BDR_MAXNODES)? BDR_MAXNODES
- : newMaxNodes) : 0);
- }
-
- voiD Binder::atIns(unsigned n, voiD D)
- {
- voiDV newLinkS;
- unsigned newLimit, i;
-
- if (!linkS || !D)
- return voiD0;
- if (nodes == limit) {
- if (limit == maxNodes)
- return voiD0;
- newLimit = (maxNodes - delta > limit)?
- limit + delta : maxNodes;
- if ((newLinkS = new voiD[newLimit])
- == voiDV0) return voiD0;
- if ((i = limit - first) > nodes)
- i = nodes;
- memcpy(newLinkS,&linkS[first],
- sizeof(linkS[0])*i);
- /* copy wrap around */
- if (i < nodes)
- memcpy(&newLinkS[i],linkS,
- sizeof(linkS[0])*(nodes-i));
- /*
- Compute next smaller linkS size
- and threshold for shrinking.
- */
- lowLimit = limit;
- lowThreshold = lowLimit - delta;
- /* swap new for old */
- delete linkS;
- linkS = newLinkS;
- limit = newLimit;
- first = 0;
- }
- if (!Dattach(D))
- return voiD0;
- if (!n) /* push */
- linkS[first? --first
- : (first = limit - 1)] = D;
- else if (n >= nodes) /* insQ */
- linkS[(first+(n=nodes))%limit] = D;
- else { /* insert interior */
- i = (first + n) % limit;
- if (i < first || !first)
- /* move rear rightward */
- memmove(&linkS[i+1],&linkS[i],
- sizeof(linkS[0])
- * (nodes-n));
- else /* move front leftward */
- memmove(&linkS[--first],&linkS[--i],
- sizeof(linkS[0])*(n+1));
- linkS[i] = D;
- }
- nodes++;
- if (n <= curNode)
- curNode++;
- flags &= ~BDR_SORTED;
- return D;
- }
-
- voiD Binder::atDel(unsigned n)
- {
- voiDV newLinkS;
- unsigned newLimit, i;
- voiD D;
-
- if (!linkS || n >= nodes)
- return voiD0;
- D = linkS[(first+n)%limit];
- if (!n) { /* pop */
- if (++first >= limit)
- first = 0;
- }
- else if (n != nodes-1) { /* del interior */
- /* move front rightward */
- memmove(&linkS[first+1],&linkS[first],
- sizeof(linkS[0])*n);
- first++;
- }
- if (--nodes == 0)
- flags |= BDR_SORTED;
- if (n < curNode)
- curNode--;
- else if (n == curNode)
- curNode = nodes;
- if (nodes < lowThreshold) {
- newLimit = lowLimit;
- if ((newLinkS = new voiD[newLimit])
- != voiDV0) {
- if ((i = limit - first) > nodes)
- i = nodes;
- memcpy(newLinkS,&linkS[first],
- sizeof(linkS[0])*i);
- /* copy wrap around */
- if (i < nodes)
- memcpy(&newLinkS[i],linkS,
- sizeof(linkS[0])
- *(nodes-i));
- /*
- Compute next smaller linkS
- size and threshold for
- shrinking.
- */
- if (lowLimit - delta > delta)
- lowLimit -= delta;
- else
- lowLimit = delta;
- lowThreshold = lowLimit - delta;
- /* swap new for old */
- delete linkS;
- linkS = newLinkS;
- limit = newLimit;
- first = 0;
- }
- }
- Ddetach(D);
- return D;
- }
-
- int Binder::allDel()
- {
- if (!linkS)
- return 0;
- while (atDel(0))
- /* null stmt */ ;
- return 1;
- }
-
- int Binder::allFree()
- {
- if (!linkS)
- return 0;
- if (flags & BDR_OK_FREE)
- while (Dfree(atDel(0)))
- /* null stmt */ ;
- return 1;
- }
-
- voiD Binder::atPut(unsigned n, voiD D)
- {
- if (linkS && D && (n < nodes))
- if (Dattach(D)) {
- flags &= ~BDR_SORTED;
- voiD& N = linkS[(first+n)%limit];
- Ddetach(N);
- if (flags & BDR_OK_FREE)
- Dfree(N);
- return (N=D);
- }
- return voiD0;
- }
-
- voiD Binder::atGet(unsigned n)
- {
- return ((linkS && (n < nodes))?
- linkS[(first+n)%limit] : voiD0);
- }
-
- voiD Binder::atXchg(unsigned n, voiD D)
- {
- if (linkS && D && (n < nodes))
- if (Dattach(D)) {
- flags &= ~BDR_SORTED;
- voiD& N = linkS[(first+n)%limit];
- voiD oldD = N;
- N = D;
- Ddetach(oldD);
- return oldD;
- }
- return voiD0;
- }
-
- unsigned Binder::index(const voiD D)
- {
- unsigned i;
-
- if (linkS && D)
- for (i = 0; i < nodes; i++)
- if (D == linkS[(first+i)%limit])
- return i;
- return BDR_NOTFOUND;
- }
-
- int Binder::forEach(BDRforEachBlocK B, voiD M, voiD A)
- {
- unsigned i;
-
- if (!linkS || !B || !nodes)
- return 0;
- for (i = 0; i < nodes; i++)
- (*B)(linkS[(first+i)%limit],M,A);
- return 1;
- }
-
- unsigned Binder::firstThat(BDRdetectBlocK B, voiD M)
- {
- unsigned i;
-
- if (linkS && B)
- for (i = 0; i < nodes; i++)
- if ((*B)(linkS[(first+i)%limit],M))
- return i;
- return BDR_NOTFOUND;
- }
-
- unsigned Binder::lastThat(BDRdetectBlocK B, voiD M)
- {
- unsigned i;
-
- if (linkS && B && nodes)
- for (i = nodes; i--; /* no reinit */)
- if ((*B)(linkS[(first+i)%limit],M))
- return i;
- return BDR_NOTFOUND;
- }
-
- int Binder::collect(BDRcollectBlocK B, BindeR R,
- voiD M, voiD A)
- {
- unsigned i;
-
- if (!linkS || !B || !R)
- return 0;
- for (i = 0; i < nodes; i++)
- (*B)(linkS[(first+i)%limit],R,M,A);
- return 1;
- }
-
-
- /* FlexList like primitives: */
-
- unsigned Binder::CurNode()
- {
- return ((curNode < nodes)?
- curNode : BDR_NOTFOUND);
- }
-
- int Binder::setCurNode(unsigned n)
- {
- return ((curNode = ((n > nodes)? nodes : n))
- < nodes);
- }
-
- Binder& Binder::operator<<(Binder& (*manipulator)
- (Binder& B))
- {
- return (manipulator? (*manipulator)(*this)
- : *this);
- }
-
- voiD Binder::ins(voiD D)
- {
- if (atIns(curNode+1,D)) {
- if (++curNode >= nodes)
- curNode = nodes - 1;
- return D;
- }
- return voiD0;
- }
-
- voiD Binder::insSort(voiD D)
- {
- unsigned low, mid, high;
- voiD ok;
-
- /*
- The current node is left undefined if
- anything fails, otherwise it is set to the
- newly inserted node.
- */
-
- curNode = nodes;
- if (!linkS || !D || nodes >= maxNodes || !comparE)
- return voiD0;
- if (!(flags & BDR_SORTED))
- if (!sort())
- return voiD0;
- low = 0;
- high = nodes;
- while (low < high) {
- mid = low + ((high - low) >> 1);
- if ((*comparE)(D,
- linkS[(first+mid)%limit]) <= 0)
- high = mid;
- else
- low = mid + 1;
- }
- if ((ok = atIns(high,D)) != voiD0)
- curNode = high;
- /* atIns() resets sorted to zero */
- flags |= BDR_SORTED;
- return ok;
- }
-
- voiD Binder::del()
- {
- voiD D;
- unsigned n;
-
- if ((D = atDel(n=curNode)) != voiD0)
- if (n--)
- curNode = n;
- return D;
- }
-
- voiD Binder::next()
- {
- if (linkS) {
- if (curNode >= nodes)
- curNode = 0;
- else
- curNode++;
- if (curNode < nodes)
- return linkS[(first+curNode)%limit];
- }
- return voiD0;
- }
-
- voiD Binder::prev()
- {
- if (linkS) {
- if (curNode) {
- if (curNode > nodes)
- curNode = nodes;
- curNode--;
- }
- else
- curNode = nodes;
- if (curNode < nodes)
- return linkS[(first+curNode)%limit];
- }
- return voiD0;
- }
-
- voiD Binder::findFirst(const voiD K)
- {
- unsigned low, mid, high;
- voiD D;
-
- /*
- The current node is left undefined if
- anything fails, otherwise it is set to the
- newly found node.
- */
-
- curNode = nodes;
- if (!linkS || !K || !comparE || !nodes)
- return voiD0;
- if (flags & BDR_SORTED) {
- low = 0;
- high = nodes;
- while (low < high) {
- mid = low + ((high - low) >> 1);
- if ((*comparE)(K,linkS[(first+mid)
- %limit]) <= 0)
- high = mid;
- else
- low = mid + 1;
- }
- if (high < nodes)
- if (!(*comparE)(K,linkS[(first+
- high)%limit]))
- return linkS[(first+
- (curNode = high))%limit];
- }
- else { /* linear search! */
- while ((D = next()) != voiD0)
- if (!(*comparE)(K,D))
- return D;
- }
- return voiD0;
- }
-
- voiD Binder::findNext(const voiD K)
- {
-
- /*
- For sorted binders you must first call findFirst()
- to insure consistent results!
- */
-
- voiD D;
-
- /*
- The current node is left undefined if
- anything fails, otherwise it is set to the
- newly found node.
- */
-
- if (!linkS || !K || !comparE) {
- curNode = nodes;
- return voiD0;
- }
- while ((D = next()) != voiD0)
- if (!(*comparE)(K,D))
- return D;
- else if (flags & BDR_SORTED) {
- curNode = nodes;
- break; /* Look no further! */
- }
- return voiD0;
- }
-
- voiD Binder::findLast(const voiD K)
- {
- unsigned low, mid, high;
- voiD D;
-
- /*
- The current node is left undefined if
- anything fails, otherwise it is set to the
- newly found node.
- */
-
- curNode = nodes;
- if (!linkS || !K || !comparE || !nodes)
- return voiD0;
- if (flags & BDR_SORTED) {
- low = 0;
- high = nodes;
- while (low < high) {
- mid = low + ((high - low) >> 1);
- if ((*comparE)(K,linkS[(first+mid)
- %limit]) < 0)
- high = mid;
- else
- low = mid + 1;
- }
- if (high < nodes)
- if (!(*comparE)(K,linkS[(first+
- high)%limit]))
- return linkS[(first+
- (curNode = high))%limit];
- }
- else { /* linear search! */
- while ((D = prev()) != voiD0)
- if (!(*comparE)(K,D))
- return D;
- }
- return voiD0;
- }
-
- voiD Binder::findPrev(const voiD K)
- {
-
- /*
- For sorted binders you must first call findLast()
- to insure consistent results!
- */
-
- voiD D;
-
- /*
- The current node is left undefined if
- anything fails, otherwise it is set to the
- newly found node.
- */
-
- if (!linkS || !K || !comparE) {
- curNode = nodes;
- return voiD0;
- }
- while ((D = prev()) != voiD0)
- if (!(*comparE)(K,D))
- return D;
- else if (flags & BDR_SORTED) {
- curNode = nodes;
- break; /* Look no further! */
- }
- return voiD0;
- }
-
- int Binder::sort(BDRcomparE comparE)
- {
- unsigned low, mid, high;
- unsigned d;
- voiD D;
-
- /*
- The current node is always reset to undefined
- regardless of the outcome of sort.
- */
-
- curNode = nodes;
- if (flags & BDR_SORTED) {
- if (this->comparE == comparE || !comparE)
- return 1;
- }
- else if (!this->comparE && !comparE)
- return 0;
- if (comparE) {
- this->comparE = comparE;
- flags &= ~BDR_SORTED;
- }
- if (!nodes)
- return (flags |= BDR_SORTED);
- if (!linkS)
- return 0;
- if (first) { /* form contiguous block at front */
- d = (first + nodes) % limit;
- if (d > first)
- memmove(linkS,&linkS[first],
- sizeof(linkS[0])*nodes);
- else if (d < first)
- memmove(&linkS[d],&linkS[first],
- sizeof(linkS[0])
- *(limit-first));
- /* else array is full/contiguous */
- first = 0;
- }
- for (high = d = 1; d < nodes; high = ++d) {
- low = 0;
- D = linkS[d];
- while (low < high) {
- mid = low + ((high - low) >> 1);
- if ((*this->comparE)(D,
- linkS[mid]) <= 0)
- high = mid;
- else
- low = mid + 1;
- }
- if (high < d) {
- memmove(&linkS[high+1],&linkS[high],
- sizeof(linkS[0])*(d-high));
- linkS[high] = D;
- }
- }
- return (flags |= BDR_SORTED);
- }
-